package cn.flying.cloud.system.service;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.common.vo.layui.MenuInfo;
import cn.flying.cloud.base.common.vo.layui.XmSelect;
import cn.flying.cloud.base.common.vo.layui.XmSelectHelper;
import cn.flying.cloud.base.common.vo.layui.ZTreeInfo;
import cn.flying.cloud.base.common.vo.vue.TreeInfoVO;
import cn.flying.cloud.system.common.enums.SeqTypeEnum;
import cn.flying.cloud.system.common.vo.ResTreeTableInfo;
import cn.flying.cloud.system.log.service.SysSeqInfoService;
import cn.flying.cloud.system.resource.entity.SysResInfo;
import cn.flying.cloud.system.resource.mapper.SysResInfoMapper;
import cn.flying.cloud.system.resource.service.SysResInfoService;
import cn.flying.cloud.system.role.service.SysRoleResService;
import cn.flying.cloud.system.user.entity.SysUserRole;
import cn.flying.cloud.system.user.service.SysUserRoleService;

/**
 * <p>
 * 资源信息表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2024-04-02 13:07:17
 */
@Service
public class SysResService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private SysSeqInfoService sysSeqInfoService;
    @Resource
    private SysResInfoService sysResInfoService;
    @Resource
    private SysResInfoMapper sysResInfoMapper;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysRoleResService sysRoleResService;

    /**
     * 获取组织机构tree数据
     *
     * @return
     */
    public List<ResTreeTableInfo> getTreeTableList(SysResInfo resInfo) {
        LambdaQueryWrapper<SysResInfo> wrapper = new LambdaQueryWrapper<>();
        if (Ft.String.isNotBlank(resInfo.getStatus())) {
            wrapper.eq(SysResInfo::getStatus, resInfo.getStatus());
        }
        wrapper.orderByAsc(SysResInfo::getResId);
        List<SysResInfo> list = sysResInfoService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<ResTreeTableInfo> treeTableInfos = list.stream().map(info -> {
            ResTreeTableInfo tableInfo = new ResTreeTableInfo();
            BeanUtils.copyProperties(info, tableInfo);
            return tableInfo;
        }).collect(Collectors.toList());

        //从根节点开始
        String parentId = Ft.String.isNotBlank(resInfo.getParentId()) ? resInfo.getParentId() : "root";
        List<ResTreeTableInfo> tableInfos = setChildren(treeTableInfos, parentId);

        return tableInfos;
    }

    private List<ResTreeTableInfo> setChildren(List<ResTreeTableInfo> list, String parentId) {
        List<ResTreeTableInfo> tableInfos = list.stream()
                // 过滤父节点
                .filter(parent -> parentId.equals(parent.getParentId()))
                // 递归赋值children
                .map(child -> {
                    List<ResTreeTableInfo> temp = setChildren(list, child.getResId());
                    if (CollectionUtils.isEmpty(temp)) {
                        child.setChildren(new ArrayList<>());
                        child.setParent(false);
                    } else {
                        child.setChildren(temp);
                        child.setParent(true);
                    }
                    return child;
                })
                .collect(Collectors.toList());
        return tableInfos;
    }

    /**
     * 查询所有的左侧导航菜单资源
     *
     * @param userId
     * @param tenantId
     * @return
     */
    public List<MenuInfo> getMenuInfos(String userId, String tenantId) {
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(userId);
        userRole.setTenantId(tenantId);
        List<SysUserRole> userRoles = sysUserRoleService.getList(userRole);
        if (CollectionUtils.isNotEmpty(userRoles)) {
            List<SysResInfo> list;
            // 如果角色包含了超级管理员（10000为超管），则直接查询全部
            Optional<String> optional = userRoles.stream().map(SysUserRole::getRoleId).filter("10000"::equals).findAny();
            if (optional.isPresent()) {
                LambdaQueryWrapper<SysResInfo> wrapper = new LambdaQueryWrapper<>();
                // 加载左侧导航菜单要排除按钮
                wrapper.ne(SysResInfo::getType, "B");
                list = sysResInfoService.list(wrapper);
            } else {
                List<SysResInfo> infos = sysResInfoMapper.getResInfosByUserId(userId, tenantId);
                if (CollectionUtils.isEmpty(infos)) {
                    return new ArrayList<>();
                }
                list = infos.stream().filter(resInfo -> !"B".equals(resInfo.getType())).collect(Collectors.toList());
            }
            Map<String, List<SysResInfo>> listMap = list.stream().collect(Collectors.groupingBy(SysResInfo::getParentId));
            List<SysResInfo> resInfos = listMap.get("root");
            List<MenuInfo> menuInfos = setMenuInfoChildren(resInfos, listMap);
            return menuInfos.get(0).getChildren();
        }
        return new ArrayList<>();
    }

    /**
     * 设置子菜单
     *
     * @param list
     * @param listMap
     * @return
     */
    private List<MenuInfo> setMenuInfoChildren(List<SysResInfo> list, Map<String, List<SysResInfo>> listMap) {
        List<MenuInfo> menuInfos = new ArrayList<>();
        list.stream().sorted(Comparator.comparing(SysResInfo::getSeq)).collect(Collectors.toList()).forEach(sysResInfo -> {

            MenuInfo menuInfoVo = new MenuInfo();
            menuInfoVo.setMenuId(sysResInfo.getResId());
            menuInfoVo.setMenuName(sysResInfo.getName());
            menuInfoVo.setTitle(sysResInfo.getTitle());
            menuInfoVo.setHref(sysResInfo.getPath());
//            menuInfoVo.setLevel(0);
            menuInfoVo.setIcon(sysResInfo.getIcon());

            List<SysResInfo> children = listMap.get(sysResInfo.getResId());
            if (CollectionUtils.isNotEmpty(children)) {
                menuInfoVo.setChildren(setMenuInfoChildren(children, listMap));
            } else {
                menuInfoVo.setChildren(new ArrayList<>());
            }
            menuInfos.add(menuInfoVo);
        });
        return menuInfos;
    }

    /**
     * 获取所有的资源树
     *
     * @return
     */
    public List<TreeInfoVO> getAllResList(String type) {
        LambdaQueryWrapper<SysResInfo> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(type)) {
            wrapper.ne(SysResInfo::getType, type);
        }
        List<SysResInfo> resInfos = sysResInfoService.list(wrapper);
        Map<String, List<SysResInfo>> listMap = resInfos.stream().collect(Collectors.groupingBy(SysResInfo::getParentId));
        List<TreeInfoVO> infoVOS = setTreeInfoChildren(listMap.get("root"), listMap);
        return infoVOS;
    }

    /**
     * 迭代设置children
     *
     * @param list
     * @param listMap
     * @return
     */
    private List<TreeInfoVO> setTreeInfoChildren(List<SysResInfo> list, Map<String, List<SysResInfo>> listMap) {
        List<TreeInfoVO> infoVOS = new ArrayList<>();
        list.stream().forEach(sysResInfo -> {
            TreeInfoVO infoVO = new TreeInfoVO();
            infoVO.setId(sysResInfo.getResId());
            infoVO.setLabel(sysResInfo.getTitle());

            List<SysResInfo> children = listMap.get(sysResInfo.getResId());
            if (CollectionUtils.isNotEmpty(children)) {
                infoVO.setChildren(setTreeInfoChildren(children, listMap));
            } else {
                infoVO.setChildren(new ArrayList<>());
            }
            infoVOS.add(infoVO);
        });
        return infoVOS;
    }

    /**
     * 查询资源下拉选
     *
     * @return
     */
    public List<XmSelect> getResourceSelectList() {
        LambdaQueryWrapper<SysResInfo> wrapper = new LambdaQueryWrapper<>();
        //这里过滤掉按钮资源
        wrapper.ne(SysResInfo::getType, "B");
        wrapper.orderByAsc(SysResInfo::getResId);
        List<SysResInfo> list = sysResInfoService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<XmSelect> xmSelects = list.stream().map(info -> {
            XmSelect xmSelect = new XmSelect();
            xmSelect.setValue(info.getResId());
            xmSelect.setName(info.getTitle());
            xmSelect.setPid(info.getParentId());
            xmSelect.setDisabled(false);
            xmSelect.setSelected(false);
            return xmSelect;
        }).collect(Collectors.toList());

        List<XmSelect> infos = XmSelectHelper.setChild(xmSelects, "root");

        return infos;
    }

    /**
     * 加载ztree 资源树形结构
     *
     * @return
     */
    public List<ZTreeInfo> getResourceTree() {
        //获取菜单
        List<SysResInfo> menuList = sysResInfoService.list();

        List<ZTreeInfo> trees = new ArrayList<>();
        ZTreeInfo tree;
        for (SysResInfo resource : menuList) {
            tree = new ZTreeInfo();
            tree.setId(resource.getResId());
            tree.setTitle(resource.getTitle());
            tree.setpId(resource.getParentId());
            trees.add(tree);
        }
        return trees;
    }


    /**
     * 新增资源信息表数据
     *
     * @param sysResInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean createObj(SysResInfo sysResInfo) {
        sysResInfo.setResId(sysSeqInfoService.getNextSeq(SeqTypeEnum.MENU.name()));


        if (!"B".equals(sysResInfo.getType()) && Ft.String.isBlank(sysResInfo.getIcon())) {
            sysResInfo.setIcon("layui-icon-component");
        }
        sysResInfoService.save(sysResInfo);

        // D目录 M菜单 B按钮
        if ("M".equals(sysResInfo.getType())) {
            // 类型为菜单，默认添加增删改查按钮
            // 列表查询
            SysResInfo query = new SysResInfo();
            query.setResId(sysSeqInfoService.getNextSeq(SeqTypeEnum.MENU.name()));
            query.setParentId(sysResInfo.getResId());
            query.setName(sysResInfo.getName() + "_list");
            query.setType("B");
            query.setSeq(1);
            query.setTitle(sysResInfo.getTitle() + "列表查询");
            query.setMid(query.getName().replace("_", ":"));
            query.setIsFrame("N");
            query.setStatus("Y");
            query.setIsShow("Y");
            query.setTenantId(Ft.Local.TenantId());
            sysResInfoService.save(query);

            // 新增按钮
            SysResInfo add = new SysResInfo();
            add.setResId(sysSeqInfoService.getNextSeq(SeqTypeEnum.MENU.name()));
            add.setParentId(sysResInfo.getResId());
            add.setName(sysResInfo.getName() + "_add");
            add.setType("B");
            add.setSeq(2);
            add.setTitle(sysResInfo.getTitle() + "新增按钮");
            add.setMid(add.getName().replace("_", ":"));
            add.setIsFrame("N");
            add.setIsShow("Y");
            add.setStatus("Y");
            add.setTenantId(Ft.Local.TenantId());
            sysResInfoService.save(add);

            // 新增按钮
            SysResInfo edit = new SysResInfo();
            edit.setResId(sysSeqInfoService.getNextSeq(SeqTypeEnum.MENU.name()));
            edit.setParentId(sysResInfo.getResId());
            edit.setName(sysResInfo.getName() + "_edit");
            edit.setType("B");
            edit.setSeq(3);
            edit.setTitle(sysResInfo.getTitle() + "编辑按钮");
            edit.setMid(edit.getName().replace("_", ":"));
            edit.setIsShow("Y");
            edit.setIsFrame("N");
            edit.setStatus("Y");
            edit.setTenantId(Ft.Local.TenantId());
            sysResInfoService.save(edit);

            // 删除按钮
            SysResInfo del = new SysResInfo();
            del.setResId(sysSeqInfoService.getNextSeq(SeqTypeEnum.MENU.name()));
            del.setParentId(sysResInfo.getResId());
            del.setName(sysResInfo.getName() + "_del");
            del.setType("B");
            del.setSeq(4);
            del.setTitle(sysResInfo.getTitle() + "删除按钮");
            del.setMid(del.getName().replace("_", ":"));
            del.setIsFrame("N");
            del.setIsShow("Y");
            del.setStatus("Y");
            del.setTenantId(Ft.Local.TenantId());
            sysResInfoService.save(del);
        }
        return true;
    }

    /**
     * 删除资源信息表数据
     *
     * @param sysResInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteObj(SysResInfo sysResInfo) {
        LambdaQueryWrapper<SysResInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysResInfo::getResId, sysResInfo.getResId());
        return sysResInfoService.remove(wrapper);
    }

}
